/*
 * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#pragma once

#include <driver/gpio.h>
#include <driver/dedic_gpio.h>
#include <hal/dedic_gpio_cpu_ll.h>
#include "hal/gpio_ll.h"

#include "compiler.h"
#include "port_common.h"
#include "pin_config.h"
#if MDLINK
/* jtag */
#define GPIO_TDI        PIN_TDI
#define GPIO_TDO        PIN_TDO
#define GPIO_TCK        PIN_SWCLK_TCK
#define GPIO_TMS        PIN_SWDIO_TMS

/* swd */
#define GPIO_SWCLK      PIN_SWCLK_TCK
#define GPIO_SWDIO      PIN_SWDIO_TMS

/* serial */
#define GPIO_BOOT       7
#define GPIO_RST        6
#define GPIO_RXD        5
#define GPIO_TXD        4
#else
/* jtag */
#define GPIO_TDI        PIN_TDI
#define GPIO_TDO        PIN_TDO
#define GPIO_TCK        PIN_SWCLK_TCK
#define GPIO_TMS        PIN_SWDIO_TMS

/* serial */
#define GPIO_BOOT       MDLINK_BOOT
#define GPIO_RST        MDLINK_RST
#define GPIO_RXD        MDLINK_UART_RX
#define GPIO_TXD        MDLINK_UART_TX

/* swd */
#define GPIO_SWCLK      PIN_SWCLK_TCK
#define GPIO_SWDIO      PIN_SWDIO_TMS
#endif //MDLINK

#if MDLINK

/* leds */
#define LED_TX          CONFIG_BRIDGE_GPIO_LED1
#define LED_RX          CONFIG_BRIDGE_GPIO_LED2
#define LED_JTAG        CONFIG_BRIDGE_GPIO_LED3

#define LED_TX_ON       CONFIG_BRIDGE_GPIO_LED1_ACTIVE
#define LED_TX_OFF      (!CONFIG_BRIDGE_GPIO_LED1_ACTIVE)

#define LED_RX_ON       CONFIG_BRIDGE_GPIO_LED2_ACTIVE
#define LED_RX_OFF      (!CONFIG_BRIDGE_GPIO_LED2_ACTIVE)

#define LED_JTAG_ON     CONFIG_BRIDGE_GPIO_LED3_ACTIVE
#define LED_JTAG_OFF    (!CONFIG_BRIDGE_GPIO_LED3_ACTIVE)
#endif /*MDLINK*/
/* 
 * 掩码值取决于在GPIO捆绑数组中的位置 
 */
/*out_offset:
            GPIO_SWCLK : 0
            GPIO_SWDIO : 1
          in_offset:
            GPIO_SWDIO : 0
        */
/* SWD IO引脚掩码值 */
#define GPIO_SWDIO_MASK     0x01 /* bundle_io_gpios[0] 输入/输出引脚 */
#define GPIO_SWDIO_MAX_MASK 0x02 /* 用作IO数组大小 1个*/

/* SWD 输出引脚掩码值 */
#define GPIO_SWCLK_MASK       0x01 /* bundle_out_gpios[0] SWD时钟线 */
//#define GPIO_SWD_BLINK_MASK   0x02 /* bundle_out_gpios[1] SWD指示灯控制 */
#define GPIO_SWD_OUT_MAX_MASK 0x02 /* 用作输出数组大小 1个*/
#define GPIO_SWDIO_OUT_MASK   0x02 /* 真实的 SWDIO输出偏移  */

/* JTAG 输出引脚掩码值 */
#define GPIO_TCK_MASK     0x01 /* JTAG测试时钟 0*/
#define GPIO_TDI_MASK     0x02 /* JTAG测试数据输入 1*/
#define GPIO_TMS_MASK     0x04 /* JTAG测试模式选择 2*/
#define GPIO_TMS_TDI_MASK 0x06 /* TMS和TDI组合掩码 (0x04 | 0x02) */

/* JTAG 输入引脚掩码值 */
#define GPIO_TDO_MASK 0x01 /* JTAG测试数据输出 */

extern dedic_gpio_bundle_handle_t s_gpio_out_bundle;
extern dedic_gpio_bundle_handle_t s_gpio_io_bundle;
extern gpio_dev_t *const s_gpio_dev;
extern uint32_t s_gpio_conf;

__STATIC_FORCEINLINE void esp_gpio_mode_input_enable(int gpio_num)
{
    gpio_ll_output_disable(s_gpio_dev, gpio_num);
    gpio_ll_input_enable(s_gpio_dev, gpio_num);
}

__STATIC_FORCEINLINE void esp_gpio_mode_out_enable(int gpio_num)
{
    gpio_ll_input_disable(s_gpio_dev, gpio_num);
    gpio_ll_output_enable(s_gpio_dev, gpio_num);
}

__STATIC_FORCEINLINE void esp_gpio_mode_in_out_enable(int gpio_num)
{
    gpio_ll_input_enable(s_gpio_dev, gpio_num);
    gpio_ll_output_enable(s_gpio_dev, gpio_num);
}

__STATIC_FORCEINLINE void esp_gpio_set(int gpio_num)
{
    gpio_ll_set_level(s_gpio_dev, gpio_num, 1);
}

__STATIC_FORCEINLINE void esp_gpio_clear(int gpio_num)
{
    gpio_ll_set_level(s_gpio_dev, gpio_num, 0);
}
/*                        SWD                          */
__STATIC_FORCEINLINE void esp_gpio_swdio_out_enable(void)
{
    REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (GPIO_SWDIO * 4), s_gpio_conf);
    gpio_ll_output_enable(s_gpio_dev, GPIO_SWDIO);
}

__STATIC_FORCEINLINE void esp_gpio_swdio_out_disable(void)
{
    gpio_ll_output_disable(s_gpio_dev, GPIO_SWDIO);
}
__STATIC_FORCEINLINE int esp_gpio_swdio_read(void)
{
    return dedic_gpio_cpu_ll_read_in();
}

__STATIC_FORCEINLINE void esp_gpio_swclk_set(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_SWCLK_MASK, GPIO_SWCLK_MASK);
}

__STATIC_FORCEINLINE void esp_gpio_swclk_clr(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_SWCLK_MASK, 0);
}

__STATIC_FORCEINLINE void esp_gpio_swdio_set(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_SWDIO_OUT_MASK, GPIO_SWDIO_OUT_MASK);
}

__STATIC_FORCEINLINE void esp_gpio_swdio_clr(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_SWDIO_OUT_MASK, 0);
}

__STATIC_FORCEINLINE void esp_gpio_swdio_write(int val)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_SWDIO_OUT_MASK, (val & 0x01) ? GPIO_SWDIO_OUT_MASK : 0);
}
/*                        SWD END                         */
#if MDLINK
__STATIC_FORCEINLINE void esp_gpio_swd_blink(int on)
{
    gpio_ll_set_level(s_gpio_dev, LED_JTAG, (on & 0x01) ? LED_JTAG_ON : LED_JTAG_OFF);
}

__STATIC_FORCEINLINE void esp_gpio_jtag_led_off(void)
{
    gpio_ll_set_level(s_gpio_dev, LED_JTAG, LED_JTAG_OFF);
}

__STATIC_FORCEINLINE void esp_gpio_jtag_led_on(void)
{
    gpio_ll_set_level(s_gpio_dev, LED_JTAG, LED_JTAG_ON);
}
#endif /*MDLINK*/
__STATIC_FORCEINLINE int esp_gpio_tdo_read(void)
{
    return dedic_gpio_cpu_ll_read_in();
}

__STATIC_FORCEINLINE void esp_gpio_tdi_write(int val)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_TDI_MASK, (val & 0x01) ? GPIO_TDI_MASK : 0);
}

__STATIC_FORCEINLINE void esp_gpio_tck_set(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_TCK_MASK, GPIO_TCK_MASK);
}

__STATIC_FORCEINLINE void esp_gpio_tck_clr(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_TCK_MASK, 0);
}
__STATIC_FORCEINLINE void esp_gpio_tms_set(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_TMS_MASK, GPIO_TMS_MASK);
}

__STATIC_FORCEINLINE void esp_gpio_tms_clr(void)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_TMS_MASK, 0);
}
__STATIC_FORCEINLINE void esp_gpio_write_tmstck(uint8_t tms_tdi_mask)
{
    dedic_gpio_cpu_ll_write_mask(GPIO_TMS_TDI_MASK, tms_tdi_mask);
}

void esp_init_jtag_pins(void);
void esp_init_swd_pins(void);
uint8_t esp_reset_dap_pins(void);
